/*
 * cubeQueue.c
 *
 *  Created on: Oct 6, 2013
 * @author Daniel Rogers
 */

#include "cubeQueue.h"

Cube deq(Queue * q)
{
    //Get the node at the head, and update where cubes are being drawn from in
    //  the node
    Cube ret;
    uint32_t set = q->head->start_pos / CUBES_PER_SET;
    uint32_t intern = q->head->start_pos % CUBES_PER_SET;
    ++q->head->start_pos;

    decompressCube(&q->head->cubes[set], intern, &ret);
    //ret = q->head->cubes[q->head->start_pos++];

    //See if the array is empty (start == where a new node would go
    if (__builtin_expect(q->head->start_pos == q->head->nxt_pos, false))
    {
        //Save the head pointer for deallocation
        Node * old = q->head;

        //Update the head to the next item in the queue
        q->head = q->head->next;

        //Deallocate the previous head node
        free(old);
    }

    return ret;
}

void enq(Queue * q, Cube cube, uint8_t layer)
{
    //See if setting up brand new queue, or end node is full
    if (__builtin_expect(isEmpty(q) || (q->tail->nxt_pos == CUBES_PER_NODE),
    false))
    {
        //Starting new queue
        Node * new;
        new = malloc(sizeof(Node));

        new->start_pos = 0;
        new->nxt_pos = 0;

        new->next = NULL;

        if (__builtin_expect(isEmpty(q), false))
        {
            //Set head to new node
            q->head = new;
        }
        else
        {
            //Appending new node to tail
            q->tail->next = new;
        }
        //Update last node to new
        q->tail = new;
    }

    //Put cube in next open position in the tail, record layer, and update next
    uint32_t set = q->tail->nxt_pos / CUBES_PER_SET;
    uint32_t intern = q->tail->nxt_pos % CUBES_PER_SET;
    compressCube(&cube, &q->tail->cubes[set], intern);
    //q->tail->cubes[q->tail->nxt_pos] = cube;
    q->tail->layers[q->tail->nxt_pos++] = layer;

}

void initQueue(Queue * q)
{
    q->head = NULL;
    q->tail = NULL;
}

bool isEmpty(Queue * const q)
{
    return q->head == NULL;
}

